package com.test.demo.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;

@Slf4j
public class JwtUtil {
    /**
     * 密钥 base64加密过的
     */
    public static final String SECRET_KEY = "Wb9^vZBjaYiFyhj@dDv!2FXSeEWxJauW";
    /**
     * 3600 = 1小时
     * 3天
     */
    public static final long EXPIRES_SECOND = 259200;
    /**
     * 签发主体
     */
    public static final String SUBJECT = "hsx";

    /**
     * token
     * @param userId
     * @return
     */
    public static String generateAppToken(Long userId) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        //生成签名密钥
        Key signingKey = generalKey();
        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .claim("userId", userId)
                .claim("date", nowMillis)
                // 是一个时间戳，代表这个JWT的签发时间；
                .setIssuedAt(now)
                // 代表这个JWT的主体，即它的所有人
                .setSubject(SUBJECT)
                .signWith(signatureAlgorithm, signingKey);
        //生成JWT
        return builder.compact();
    }

    /**
     * 解密token
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static Claims parseJwt(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(generalKey())
                    .parseClaimsJws(token).getBody();
        } catch (Exception e) {
            log.error("token解析异常");
            return null;
        }
    }

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    private static Key generalKey() {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET_KEY);
        return new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
    }

    /**
     * 设置token过期时间
     *
     * @param nowMillis
     * @param now
     * @param builder
     */
    private static void expiresTime(long nowMillis, Date now, JwtBuilder builder) {
        //添加Token过期时间
        if (EXPIRES_SECOND >= 0) {
            long expMillis = nowMillis + EXPIRES_SECOND;
            Date exp = new Date(expMillis);
            // 是一个时间戳，代表这个JWT的过期时间；
            builder.setExpiration(exp)
                    // 是一个时间戳，代表这个JWT生效的开始时间，意味着在这个时间之前验证JWT是会失败的
                    .setNotBefore(now);
        }
    }
}
